library MhFlutterAmapSearch;
import 'dart:async';
import 'dart:convert' as convert;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
// import 'src/models/latlng.dart';
// import 'src/models/models.dart';
part 'src/models/latlng.dart';
part 'src/models/models.dart';
class MhFlutterAmapSearch {
  static MethodChannel _channel = const MethodChannel('mh_flutter_amap_search')
    ..setMethodCallHandler(_hander);

  static List<Completer> _keywordCompleters = [];
  static List<Completer> _aroundCompleters = [];
  static List<Completer> _poiIdCompleters = [];
  static List<Completer> _inputTipCompleters = [];
  static List<Completer> _geocodeCompleters = [];
  static List<Completer> _reGeocodeCompleters = [];
  static List<Completer> _distanceCompleters = [];

  
  static Future<String> get platformVersion async {
    final String version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }

  static setApiKey(String iosKey,  String androidKey) {
    _channel.invokeMethod(
        'setApiKey', {"iosKey": iosKey, "androidKey": androidKey});
  }

  static Future<List<Poi>> searchKeyword(
    //
    String keyword, {
    String city = '',
    int pageSize = 20,
    int page = 1,
  }) async {
    assert(page > 0 && page < 100, '页数范围为1-100');
    assert(pageSize > 0 && pageSize < 50, '每页大小范围为1-50');
    final completer = Completer<List<Poi>>();
    _keywordCompleters.add(completer);
    _channel.invokeMethod('searchKeyword',
        {"keyword": keyword, "city": city, "pageSize": pageSize, "page": page});
    return completer.future;
  }

  /// 周边搜索poi
  ///
  /// 在中心点[center]周边搜索关键字[keyword]和城市[city]的poi, 可以设置每页数量[pageSize](1-50)和第[page](1-100)页
  static Future<List<Poi>> searchAround(
    LatLng center, {
    String keyword = '',
    String city = '',
    String type = '',
    int pageSize = 20,
    int page = 1,
    int radius = 1000,
  }) async {
    var completer = Completer<List<Poi>>();
    _aroundCompleters.add(completer);
    _channel.invokeMethod('searchAround', {
      "keyword": keyword,
      "city": city,
      "pageSize": pageSize,
      "page": page,
      "radius": radius,
      "latitude": center.latitude,
      "longitude": center.longitude
    });
    return completer.future;
  }

  /// id搜索poi
  static Future<Poi> searchPoiId(String id) async {
    var completer = Completer<List<Poi>>();
    _poiIdCompleters.add(completer);
    _channel.invokeMethod("searchPoiId", {"uid": id});
    return completer.future.then((value) => value.first);
  }
  /// destination 目的地坐标 ，origins 起点坐标数组 type：0直线距离 1驾车导航距离 2步行导航距离
  static Future<int> searchDistance({
    required LatLng destination,
    required List<LatLng> origins,
    int type = 0,
})async{
  var completer = Completer<int>();
  _distanceCompleters.add(completer);
  var args = {
    "type":type,
    "destination": {
      "latitude":destination.latitude,
      "longitude": destination.longitude
    },
    "origins": origins.map((e) => {
      "latitude":e.latitude,
      "longitude": e.longitude
    }).toList()
  };
  _channel.invokeMethod("distanceSearch", args);
  return completer.future;
}

  /// 输入内容自动提示
  ///
  /// 输入关键字[keyword], 并且限制所在城市[city]
  static Future<List<InputTip>> fetchInputTips(
    String keyword, {
    String city = '',
  }) async {
    var completer = Completer<List<InputTip>>();
    _inputTipCompleters.add(completer);
    _channel
        .invokeMethod("fetchInputTips", {"keyword": keyword, "city": city});
    return completer.future;
  }

  /// 地理编码（地址转坐标）
  ///
  /// 输入关键字[keyword], 并且限制所在城市[city]
  static Future<List<Geocode>> searchGeocode(
    String address, {
    String city = '',
  }) async {
    var completer = Completer<List<Geocode>>();
    _geocodeCompleters.add(completer);
    _channel.invokeMethod("searchGeocode", {"address": address, "city": city});
    return completer.future;
  }

  /// 逆地理编码（坐标转地址）
  ///
  /// 输入关键字[keyword], 并且限制所在城市[city]
  static Future<ReGeocode> searchReGeocode(
    LatLng latLng, {
    double radius = 200.0,
  }) async {
    var completer = Completer<ReGeocode>();
    _reGeocodeCompleters.add(completer);
    _channel.invokeMethod("searchReGeocode", {
      "latitude": latLng.latitude,
      "longitude": latLng.longitude,
      "radius": radius
    });
    return completer.future;
  }

  static Future<dynamic> _hander(MethodCall call){
    if (call.method == "onPOISearchDone") {
      var requestType = call.arguments["requestType"] as String;
      var list = call.arguments["pois"] as List;
      var resultList = <Poi>[];
      for (var poiMap in list){
        // debugPrint('poimap$poiMap');
        resultList.add(Poi.fromJson(Map<String, dynamic>.from(poiMap)));
      }
      if(requestType == "keySearch"){
        _keywordCompleters.first.complete(resultList);
        _keywordCompleters.removeAt(0);
      }else if(requestType == "aroundSearch"){
        _aroundCompleters.first.complete(resultList);
        _aroundCompleters.removeAt(0);
      }else{
        _poiIdCompleters.first.complete(resultList);
        _poiIdCompleters.removeAt(0);
      }
    } else if (call.method == "onInputTipsSearchDone") {
      var list = call.arguments["tips"] as List;
      var resultList = <InputTip>[];
      for (var inputMap in list){
        resultList.add( InputTip.fromJson(Map<String, dynamic>.from(inputMap)));
      }
      _inputTipCompleters.first.complete(resultList);
      _inputTipCompleters.removeAt(0);
    } else if (call.method == "onGeocodeSearchDone") {
      var list = call.arguments["geocodes"] as List;
      var resultList = <Geocode>[];
      for (var geoMap in list){
        resultList.add( Geocode.fromJson(Map<String, dynamic>.from(geoMap)));
      }
      _geocodeCompleters.first.complete(resultList);
      _geocodeCompleters.removeAt(0);
    } else if (call.method == "onReGeocodeSearchDone") {
      var item = call.arguments["regeocode"];
      var map = Map<String, dynamic>.from(
          convert.jsonDecode(convert.jsonEncode(item)));
      var regeo = ReGeocode.fromJson(map);
      _reGeocodeCompleters.first.complete(regeo);
      _reGeocodeCompleters.removeAt(0);
    }else if (call.method == "onDistanceSearchDone"){
      var list = call.arguments["distanceList"] as List;
      var item = list.first;
      var distance = item["distance"] as int;
      _distanceCompleters.first.complete(distance);
      _distanceCompleters.removeAt(0);
    } else if (call.method == "onAMapSearchRequest_didFailWithError") {
      var requestType = call.arguments["requestType"] as String;
      var errMessage = call.arguments["errMessage"] as String;
      switch(requestType){
        case "keySearch": {
          _keywordCompleters.first.completeError({"errMessage":errMessage});
          _keywordCompleters.removeAt(0);
        }
        break;
        case "aroundSearch": {
          _aroundCompleters.first.completeError({"errMessage":errMessage});
          _aroundCompleters.removeAt(0);
        }
        break;
        case "idSearch":{
          _poiIdCompleters.first.completeError({"errMessage":errMessage});
          _poiIdCompleters.removeAt(0);
        }
        break;
        case "geoSearch":{
          _geocodeCompleters.first.completeError({"errMessage":errMessage});
          _geocodeCompleters.removeAt(0);
        }
        break;
        case "reGeoSearch":{
          _reGeocodeCompleters.first.completeError({"errMessage":errMessage});
          _reGeocodeCompleters.removeAt(0);
        }
        break;
        case "inputTipsSearch":{
          _inputTipCompleters.first.completeError({"errMessage":errMessage});
          _inputTipCompleters.removeAt(0);
        }
        break;
        case "distanceSearch":{
          _distanceCompleters.first.completeError({"errMessage":errMessage});
          _distanceCompleters.removeAt(0);
        }
        break;
      }

    }
    return Future.value(true);
  }
}
